package net.helix.ui.panels.library;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.image.BufferedImage;

import javax.swing.tree.TreePath;

import org.jdesktop.swingx.JXTreeTable;

public class LibraryTreeDropTarget extends DropTarget{
	private static final long serialVersionUID = 1L;
	
	LibraryTreeTableModel model;
	LibraryTreeTransferHandler handler;
	public LibraryTreeDropTarget(LibraryTreeTableModel model, LibraryTreeTransferHandler handler){
		this.model = model;
		this.handler = handler;
	}
	public void dragOver(DropTargetDragEvent dropTargetDragEvent) {
		System.out.println("dragOver");
		
		if(model.useFilter == false){
			Point location = dropTargetDragEvent.getLocation();
			JXTreeTable tree = (JXTreeTable) dropTargetDragEvent.getDropTargetContext().getComponent();
			
			updateDragMark(tree, location);
		    paintImage(tree, location);
		    autoscroll(tree, location);
		}
		super.dragOver(dropTargetDragEvent);
	}
	private Rectangle rect2D = new Rectangle();
	private final void paintImage(JXTreeTable tree, Point pt) {
		for(int i=0;i<handler.getNumberOfDraggedNodes();i++){
		
			BufferedImage image = handler.getDragImage(tree, i);
			if(image != null) {
				// TODO: fix support for multiple images when dragging...
				tree.paintImmediately(rect2D.getBounds());
				rect2D.setRect((int) pt.getX()-15, (int) pt.getY()-15  + i*30, image.getWidth(), image.getHeight());
				tree.getGraphics().drawImage(image, (int) pt.getX()-15, (int) pt.getY()-15 + i*30, tree);
			}
		}
	}
	
	private void markNode(JXTreeTable tree, Point location) {
		TreePath path = tree.getPathForLocation(location.x, location.y);
		int row = tree.getRowForPath(path);
		if(path != null) {
			if(lastRowBounds != null) {
				Graphics g = tree.getGraphics();
				g.setColor(Color.white);
				g.drawLine(lastRowBounds.x, lastRowBounds.y, 
						lastRowBounds.x + lastRowBounds.width, lastRowBounds.y);
			}
			tree.setRowSelectionInterval(row, row);
			
			// feels annoying if they auto expand when you have large folders
			//tree.expandPath(path);
		}
	}
	
	private int insertAreaHeight = 8;
	
	private Point mostRecentLocation;
	public Point getMostRecentDragLocation() {
		return mostRecentLocation;
	}
	public void updateDragMark(JXTreeTable tree, Point location) {
		mostRecentLocation = location;
		int row = tree.getRowForPath(tree.getPathForLocation(location.x, location.y));
		TreePath path = tree.getPathForRow(row);
		if(path != null) {
			Rectangle rowBounds = tree.getCellRect(row, 0, false);
			
			int rby = rowBounds.y;
			int topBottomDist = insertAreaHeight / 2;
			Point topBottom = new Point(rby - topBottomDist, rby + topBottomDist);
			if(topBottom.x <= location.y && topBottom.y >= location.y) {
				paintInsertMarker(tree, location);
			}else {
				markNode(tree, location);
			}
		}
	}
	private Rectangle lastRowBounds;
	
	private void paintInsertMarker(JXTreeTable tree, Point location) {
		Graphics g = tree.getGraphics();
		tree.clearSelection();
		int row = tree.getRowForPath(tree.getPathForLocation(location.x, location.y));
		TreePath path = tree.getPathForRow(row);
		if(path != null) {
			Rectangle rowBounds = tree.getCellRect(row, 0, false); //tree.getPathBounds(path);
			if(lastRowBounds != null) {
				g.setColor(Color.white);
				g.drawLine(lastRowBounds.x, lastRowBounds.y, 
						lastRowBounds.x + lastRowBounds.width, lastRowBounds.y);
			}
			if(rowBounds != null) {
				g.setColor(Color.black);
				g.drawLine(rowBounds.x, rowBounds.y, rowBounds.x + rowBounds.width, rowBounds.y);
			}
			lastRowBounds = rowBounds;
		}
	}
	
	private Insets autoscrollInsets = new Insets(20, 20, 20, 0); // 20, 20, 20, 20
	private Insets getAutoscrollInsets() {
		return autoscrollInsets;
	}
	private void autoscroll(JXTreeTable tree, Point cursorLocation) {
		Insets insets = getAutoscrollInsets();
		Rectangle outer = tree.getVisibleRect();
		Rectangle inner = new Rectangle(
				outer.x+insets.left,
				outer.y+insets.top,
				outer.width-(insets.left+insets.right),
				outer.height-(insets.top+insets.bottom));
		if (!inner.contains(cursorLocation))  {
			Rectangle scrollRect = new Rectangle(
					cursorLocation.x-insets.left,
					cursorLocation.y-insets.top,
					insets.left+insets.right,
					insets.top+insets.bottom);
			tree.scrollRectToVisible(scrollRect);
		}
	}
	
	@Override
	public void dragEnter(DropTargetDragEvent arg0) {
		//System.out.println("dragEnter");
		model.isMouseOver = true;
	}
	@Override
	public void dragExit(DropTargetEvent arg0) {
		//System.out.println("dragExit");
		model.isMouseOver = false;
	}

}
